package com.jyu.game;

import com.jyu.domain.Tetris;
import com.jyu.util.Cell;
import com.jyu.util.RotateStatus;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;

public class GameJFrame extends JFrame implements KeyListener {

    public static BufferedImage I;
    public static BufferedImage J;
    public static BufferedImage L;
    public static BufferedImage O;
    public static BufferedImage S;
    public static BufferedImage T;
    public static BufferedImage Z;
    public static BufferedImage Background;

    private Cell[][] wall = new Cell[18][9];
    private final int CELL_SIZE = 48;
    private Tetris currentTetris = Tetris.randomTetris();
    private Tetris nextTetris = Tetris.randomTetris();
    private int score = 0;
    private int[] scorePool = {0, 1, 2, 5, 10};
    private int line = 0;
    private final int PLAYING = 0;
    private final int PAUSE = 1;
    private final int GAMEOVER = 2;
    private final int WIN = 3;
    private int game_status = 0;

    private String[] result = {
            "P [pause]",
            "C [continue]",
            "R [restart]"
    };

    //静态代码块将7个图形先加载进来，方便后面使用
    static {
        try {
            I = ImageIO.read(new File("images/I.png"));
            J = ImageIO.read(new File("images/J.png"));
            L = ImageIO.read(new File("images/L.png"));
            O = ImageIO.read(new File("images/O.png"));
            S = ImageIO.read(new File("images/S.png"));
            T = ImageIO.read(new File("images/T.png"));
            Z = ImageIO.read(new File("images/Z.png"));
            Background = ImageIO.read(new File("images/background.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    public GameJFrame() {
        //初始化游戏窗口
        initJFrame();
        //初始化游戏界面
        initJPanel();
        //初始化定时器(游戏运行)
        initTimer();
        //设置游戏窗口可见
        setVisible(true);
    }

    private void initTimer() {
        Timer timer = new Timer();
        //任务
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                //判断游戏的状态
                if (game_status == PLAYING) {
                    //判断俄罗斯方块是否能下落
                    if (canDown()) {
                        //如果可以，就一直下落
                        currentTetris.moveDown();
                    } else {
                        //嵌入到墙中
                        landToWall();
                        //判断是否能消行
                        destroyLines();
                        //判断游戏状态
                        if (isGameOver()) {
                            //将游戏状态设置为结束
                            game_status = GAMEOVER;
                        } else {
                            //将下一个俄罗斯方块赋值给当前俄罗斯方块
                            currentTetris = nextTetris;
                            //重新生成下一个俄罗斯方块
                            nextTetris = Tetris.randomTetris();
                        }
                    }
                }
                //重新执行paint方法，即initJPanel
                repaint();
            }
        };
        //让任务反复执行
        timer.scheduleAtFixedRate(timerTask, 0, 200);
    }

    //俄罗斯方块向右旋转
    public void rotataRightDirection() {
        currentTetris.rotateRight();
        if (isOutOfBounds() || isCoincide()) {
            currentTetris.rotateLeft();
        }
    }

    //俄罗斯方块向左旋转
    public void rotataLeftDirection() {
        currentTetris.rotateLeft();
        if (isOutOfBounds() || isCoincide()) {
            currentTetris.rotateRight();
        }
    }

    //判断游戏是否结束
    private boolean isGameOver() {
        Cell[] cells = nextTetris.getCells();
        for (Cell cell : cells) {
            int col = cell.getCol();
            int row = cell.getRow();
            if (wall[row][col] != null) {
                return true;
            }
        }
        return false;

    }

    //消除行数
    private void destroyLines() {
        int destroy_line = 0;
        Cell[] cells = currentTetris.getCells();
        for (Cell cell : cells) {
            int row = cell.getRow();
            int col = cell.getCol();
            if (canDestroy(row)) {
                destroy_line++;
                for (int i = row; i > 0; i--) {
                    System.arraycopy(wall[row - 1], 0, wall[row], 0, wall[0].length);
                }
                wall[0] = new Cell[9];
            }
        }
        if (destroy_line < scorePool.length - 1) {
            this.line += destroy_line;
            this.score += scorePool[destroy_line];
        } else if (destroy_line >= scorePool.length - 1) {
            this.line += destroy_line;
            this.score += scorePool[scorePool.length - 1];
        }
    }

    //判断是否可以消除
    private boolean canDestroy(int row) {
        Cell[] cells = wall[row];
        for (Cell cell : cells) {
            if (cell == null) {
                return false;
            }
        }
        return true;
    }

    //将俄罗斯方块装进墙
    private void landToWall() {
        Cell[] cells = currentTetris.getCells();
        for (Cell cell : cells) {
            int col = cell.getCol();
            int row = cell.getRow();
            wall[row][col] = cell;
        }

    }

    private void initJPanel() {
        JPanel jPanel = new JPanel() {
            @Override
            public void paintComponent(Graphics g) {
                //清空游戏界面
                super.paintComponent(g);
                //加载游戏背景
                g.drawImage(Background, 0, 0, null);
                //平移坐标轴
                g.translate(22, 14);
                //绘制游戏主区域
                paintWall(g);
                //绘制正在下落的俄罗斯方块
                paintCurrentTetris(g);
                //绘制下一个下落的俄罗斯方块
                paintNextTetris(g);
                //绘制游戏得分
                paintScores(g);
                //绘制消除的行数
                paintLines(g);
                //绘制游戏状态
                paintStates(g);
            }
        };
        this.getContentPane().add(jPanel);
    }

    //判断俄罗斯方块是否可以下落
    private boolean canDown() {
        Cell[] cells = currentTetris.getCells();
        for (Cell cell : cells) {
            int row = cell.getRow();
            int col = cell.getCol();
            //判断是否到达底部
            if (row == wall.length - 1) {
                return false;
            } else if (wall[row + 1][col] != null) { //判断是否有方块
                return false;
            }
        }
        return true;
    }

    private void paintStates(Graphics g) {
        g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 35));
        if (this.score >= 15) {
            g.setColor(Color.red);
            g.drawString(result[GAMEOVER], 526, 665);
            g.setColor(Color.red);
            g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 70));
            g.setColor(Color.YELLOW);
            game_status = WIN;
            g.drawString("WIN!", 140, 457);

            g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 35));
            g.drawString("Would you want to", 60, 500);
            g.drawString(" play again?", 100, 550);
        }

        if (game_status != WIN) {
            if (game_status == PLAYING) {
                g.drawString(result[PLAYING], 526, 665);
            } else if (game_status == PAUSE) {
                g.drawString(result[PAUSE], 526, 665);
            } else if (game_status == GAMEOVER) {
                g.drawString(result[GAMEOVER], 526, 665);
                g.setColor(Color.red);
                g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 70));
                g.drawString("GAMEOVER!", 3, 457);
            }
        }
    }

    private void paintLines(Graphics g) {
        g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 35));
        g.drawString("LINES: " + line, 526, 438);
    }

    private void paintScores(Graphics g) {
        g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 35));
        g.drawString("SCORES: " + score, 520, 250);
    }

    private void paintNextTetris(Graphics g) {

        Cell[] cells = nextTetris.getCells();
        for (Cell cell : cells) {
            int y = cell.getRow() * CELL_SIZE;
            int x = cell.getCol() * CELL_SIZE;
            g.drawImage(cell.getBufferedImage(), x + 402, y + 17, null);
        }
        g.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 25));
        g.drawString("NEXT:", 467, 32);
    }

    private void paintCurrentTetris(Graphics g) {
        Cell[] cells = currentTetris.getCells();
        for (Cell cell : cells) {
            int y = cell.getRow();
            int x = cell.getCol();
            g.drawImage(cell.getBufferedImage(), x * CELL_SIZE, y * CELL_SIZE, null);
        }

    }

    private void paintWall(Graphics g) {
        for (int i = 0; i < wall.length; i++) {
            for (int j = 0; j < wall[0].length; j++) {
                int x = j * CELL_SIZE;
                int y = i * CELL_SIZE;
                Cell cell = wall[i][j];
                if (cell == null) {
                    g.drawRect(x, y, CELL_SIZE, CELL_SIZE);
                } else {
                    g.drawImage(cell.getBufferedImage(), x, y, null);
                }
            }
        }
    }

    private void initJFrame() {
        //设置游戏图标
        this.setIconImage(Toolkit.getDefaultToolkit().getImage("images\\head1.png"));
        //设置游戏名字
        setTitle("俄罗斯方块 v_1.0 单机版");
        //设置游戏大小
        setSize(810, 937);
        //设置默认关闭方式
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //设置界面置顶
        setAlwaysOnTop(true);
        //设置游戏界面居于电脑屏幕中间
        setLocationRelativeTo(null);
        //设置游戏界面大小不可调节
        setResizable(false);


        addKeyListener(this);
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
        switch (keyCode) {
            case KeyEvent.VK_LEFT: {
                System.out.println("按下了←键");
                //俄罗斯方块整体向左移动一格
                moveLeftDirection();
                break;
            }
            case KeyEvent.VK_RIGHT: {
                //俄罗斯方块整体向右移动一格
                System.out.println("按下了→键");
                moveRightDirection();
                break;
            }
            case KeyEvent.VK_C: {
                //游戏回复运行状态
                System.out.println("按下了C键");
                if (game_status == PAUSE) {
                    game_status = PLAYING;
                }
                break;
            }
            case KeyEvent.VK_P: {
                //游戏暂停
                System.out.println("按下了P键");
                if (game_status == PLAYING) {
                    game_status = PAUSE;
                }
                break;
            }
            case KeyEvent.VK_R: {
                //游戏重新开始
                System.out.println("按下了R键");
                game_status = PLAYING;
                wall = new Cell[18][9];
                this.score = 0;
                this.line = 0;
                currentTetris = Tetris.randomTetris();
                nextTetris = Tetris.randomTetris();
                break;
            }
            case KeyEvent.VK_A: {
                System.out.println("按下了A键");
                //俄罗斯方块逆时针旋转
                rotataLeftDirection();
                break;
            }
            case KeyEvent.VK_D: {
                System.out.println("按下了D键");
                //俄罗斯方块顺时针旋转
                rotataRightDirection();
                break;
            }
            case KeyEvent.VK_DOWN: {
                System.out.println("按下了↓键");
                //俄罗斯方块整体向下移动一格
                moveDownDirection();
                break;
            }
            case KeyEvent.VK_SPACE: {
                System.out.println("按下了空格键");
                //俄罗斯方块瞬间下落到最下面
                momentDrop();
                break;
            }
        }
    }

    //实现俄罗斯方块下移
    private void moveDownDirection() {
        if (canDown()) {
            currentTetris.moveDown();
        }
    }

    //实现俄罗斯方块左移
    private void moveLeftDirection() {
        currentTetris.moveLeft();
        if (isOutOfBounds() || isCoincide()) {
            currentTetris.moveRight();
        }
    }

    //实现俄罗斯方块右移
    private void moveRightDirection() {
        currentTetris.moveRight();
        if (isOutOfBounds() || isCoincide()) {
            currentTetris.moveLeft();
        }
    }

    //判断俄罗斯方块是否越界
    public boolean isOutOfBounds() {
        Cell[] cells = currentTetris.getCells();
        for (Cell cell : cells) {
            int col = cell.getCol();
            int row = cell.getRow();
            if (col < 0 || col > wall[0].length - 1 || row < 0 || row > wall.length - 1) {
                return true;
            }
        }
        return false;
    }

    //判断俄罗斯方块是否重合
    public boolean isCoincide() {
        Cell[] cells = currentTetris.getCells();
        for (Cell cell : cells) {
            int col = cell.getCol();
            int row = cell.getRow();
            if (wall[row][col] != null) {
                return true;
            }
        }
        return false;

    }

    //实现俄罗斯方块瞬间下落
    private void momentDrop() {
        while (true) {
            if (canDown()) {
                currentTetris.moveDown();
            } else {
                break;
            }
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }
}

